﻿using PivotData;
using System.Collections;
using System.IO;
using System.Linq;

namespace PivotIO.XML
{
    /// <summary>
    /// Run i/o for a list of images along with all meta data.
    /// </summary>
    public class ImageInfoIO : PerCollectionDataIO<ImageInfo>
    {
        static ImageInfoIO()
        {
            IOName = "Images.xml";
        }

        /// <summary>
        /// Load the XML DB for images given a collection id from the default location.
        /// </summary>
        /// <param name="collectionId"></param>
        /// <returns></returns>
        public static ImageInfo[] LoadAllImages(int collectionId)
        {
            return LoadAll(collectionId);
        }

        /// <summary>
        /// Load all images given a directory.
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static ImageInfo[] LoadAllImages(DirectoryInfo dir)
        {
            return LoadAll(dir);
        }

        /// <summary>
        /// Save all collections to our specific output file.
        /// </summary>
        /// <param name="images"></param>
        public static void SaveAllImages(int collectionId, ImageInfo[] images)
        {
            SaveAll(collectionId, images);
        }

        /// <summary>
        /// Delete the images directory - everything will be lost forever!
        /// </summary>
        /// <param name="collectionId"></param>
        public static void DeleteAllImages(int collectionId)
        {
            DeleteAll(collectionId);
        }

        /// <summary>
        /// Save an image. Save only if the image is new. If the data being sent in is identical to
        /// what is already there on disk, then we just ignore it.
        /// </summary>
        /// <param name="cId">Collection identifier</param>
        /// <param name="iId">Image identifier</param>
        /// <param name="p3">Image type (png, jpg, etc.)</param>
        /// <param name="data">Data that should be written to the file</param>
        /// <returns>True if the files was written or updated, false if nothign was written.</returns>
        public static bool SaveImage(int cId, int iId, string extension, byte[] data)
        {
            // See if there is an old image on disk. And if there is, if the data is the same.

            var iFIO = new FileInfo(Path.Combine(Utils.GetROOTDataDirectory().FullName, cId.ToString(), string.Format("{0}.{1}", iId.ToString(), extension)));
            if (!iFIO.Directory.Exists)
                iFIO.Directory.Create();

            if (iFIO.Exists)
            {
                if (iFIO.Length == data.Length)
                {
                    using (var reader = iFIO.OpenRead())
                    {
                        var oldData = new byte[iFIO.Length];
                        reader.Read(oldData, 0, oldData.Length);
                        if ((oldData as IStructuralEquatable).Equals(data, StructuralComparisons.StructuralEqualityComparer))
                            return false;
                    }
                }
            }

            // If we are here, then we need to write out the file.

            using (var output = iFIO.Create())
            {
                output.Write(data, 0, (int)data.Length);
                return true;
            }
        }

        /// <summary>
        /// Return all facets used by a collection's images.
        /// </summary>
        /// <param name="cId"></param>
        /// <returns></returns>
        public static string[] GetDefaultFacetNames(int cId)
        {
            var images = LoadAllImages(cId);
            var fnames = from i in images
                         from f in i.Facets
                         select f.Name;

            return fnames.Distinct().ToArray();
        }
    }
}